package com.gitee.flow.ext;

import com.gitee.jmash.rbac.client.RbacClient;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jmash.rbac.protobuf.UserList;
import jmash.rbac.protobuf.UserModel;
import jmash.rbac.protobuf.UserReq;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.flowable.common.engine.api.delegate.Expression;
import org.flowable.task.service.delegate.DelegateTask;
import org.flowable.task.service.delegate.TaskListener;

/**
 * 通过表达式分配用户和候选人.
 *
 * @author cgd
 */
public class AssignmentHandler implements TaskListener {

  private static final long serialVersionUID = 1L;
  private static final Log log = LogFactory.getLog(AssignmentHandler.class);

  /** 分配的表达式. */
  private Expression assignee;

  /*
   * (non-Javadoc)
   * 
   * @see
   * org.activiti.engine.delegate.TaskListener#notify(org.activiti.engine.delegate.DelegateTask)
   */
  public void notify(DelegateTask delegateTask) {
		String assignees = assignee.getExpressionText();		
		List<String> users = procAssignee(delegateTask.getTenantId(),assignees);
		if (users.size() == 1) {
			delegateTask.setAssignee(users.get(0));
		}
		if (users.size() > 1) {
			delegateTask.addCandidateUsers(users);
		}
	}

  /**
   * 处理表达式.
   *
   * @param assignee 分配人.
   */
  public List<String> procAssignee(String tenant, String assignee) {
    if (StringUtils.isEmpty(assignee)) {
      return Collections.emptyList();
    }
    List<String> users = new ArrayList<String>();
    List<String[]> list = findTags(assignee);
    for (String[] tag : list) {
      if ("role".equals(tag[0])) {
        Map<String, String> params = findAttributes(tag[1]);
        users.addAll(findOrganUser(tenant, params));
      }
    }
    return users;
  }

  /**
   * 获取用户.
   *
   * @param params 参数
   */
  public List<String> findOrganUser(String tenant, Map<String, String> params) {
    List<String> users = new ArrayList<String>();
    if (params.containsKey("name")) {
      String roleName = params.get("name");
      log.debug(roleName);
      UserList userlist = RbacClient.getRbacBlockingStub()
          .findUserList(UserReq.newBuilder().setTenant(tenant).setRoleCode(roleName).build());
      for (UserModel user : userlist.getResultsList()) {
        users.add(user.getUserId());
      }
    }
    return users;
  }

  /**
   * role(leader),organ(organ(type=treasury)).
   *
   * @param assignee 表达式.
   */
  public static List<String[]> findTags(String assignee) {
    Pattern p = Pattern.compile("(\\w+)\\(([\\w=,]+)\\)");
    Matcher m = p.matcher(assignee);
    List<String[]> list = new ArrayList<String[]>();
    while (m.find()) {
      list.add(new String[] {m.group(1).trim(), m.group(2).trim()});
    }
    return list;
  }

  /**
   * name type=treasury,.
   *
   * @param attributes 属性
   */
  public static Map<String, String> findAttributes(String attributes) {
    Pattern p = Pattern.compile("(\\w+)=(\\w+)");
    Matcher m = p.matcher(attributes);
    Map<String, String> map = new HashMap<String, String>();
    while (m.find()) {
      map.put(m.group(1).trim(), m.group(2).trim());
    }
    if (map.size() == 0) {
      map.put("name", attributes);
    }
    return map;
  }

  public static void main(String[] args) {
    AssignmentHandler handler = new AssignmentHandler();
    handler.procAssignee("rbac", "role(name=N_D_staffing_audit)");
  }

}
